/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.foxline.manager.create;

import br.com.foxline.enums.*;
import br.com.foxline.model.*;
import br.com.foxline.service.CityService;
import br.com.foxline.service.CorrectorService;
import br.com.foxline.service.CustomerService;
import br.com.foxline.service.EnterpriseService;
import br.com.foxline.service.LotService;
import br.com.foxline.service.MessageService;
import br.com.foxline.service.PendingService;
import br.com.foxline.service.SaleService;
import br.com.foxline.service.UserService;
import br.com.foxline.util.Caracter;
import br.com.foxline.util.Msg;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.SessionScoped;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import org.primefaces.component.wizard.Wizard;
import org.primefaces.context.RequestContext;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.event.FlowEvent;

/**
 *
 * @author luciano
 */
@ManagedBean
@ViewScoped
public class ManagerCreateSale implements Serializable {

    private DiscountType discountType = DiscountType.PERCENT;
    private PaymentType paymentType = PaymentType.AT_SIGHT;
    private boolean hasInterest = true;
    private Enterprise enterprise;
    private Lot lot;
    private Integer block;
    @EJB
    private EnterpriseService enterpriseService;
    @EJB
    private LotService lotService;
    @EJB
    private CustomerService customerService;
    @EJB
    private CityService cityService;
    @EJB
    private SaleService saleService;
    @EJB
    private PendingService pendingService;
    @EJB
    private MessageService messageService;
    @EJB
    private UserService userService;
    @EJB
    private CorrectorService correctorService;
    private Corrector corrector;
    //A vista
    private BigDecimal discount;
    private BigDecimal totalSighting = new BigDecimal(0);
    //Parcelada
    private BigDecimal beginValue = new BigDecimal(0);
    private ValueInterestParcel valueInterestParcel = new ValueInterestParcel();
    //Personalizada
    private BigDecimal beginValueCustom = new BigDecimal(0);
    private BigDecimal qtde = new BigDecimal(0);
    private BigDecimal juros = new BigDecimal(0);
    private BigDecimal parcelValue = new BigDecimal(0);
    private BigDecimal totalValueCustom = new BigDecimal(0);
    ///Customer
    private Customer customer;
    private Address address;
    private List<Address> addresses;
    private City city;
    private Customer conjuge;
    private Annex annex;
    private List<Annex> annexs;
    private Customer aux = new Customer();
    ///Informations
    private Annex annexInfo;
    private List<Annex> attachments;
    ///Sale
    private Sale sale;
    private boolean conjugeVisible;
    private boolean addressRequired = true; 
    private boolean canSale = true;
    public void save() {
        try {
            this.sale.setEnterprise(enterprise);
            lot.setStatus(Status.TRAMITE);
            this.sale.setLot(lot);
            this.customer.setSpouse(conjuge);
            this.sale.setSaleDate(new Date());
            this.sale.setStatusSale(StatusSale.WAITING_APPROVAL);
            this.sale.setPaymentType(paymentType);
            this.sale.setCorrector(this.corrector);
            if (customer.getId() == null) {
                this.customer.setAddresses(addresses);
                customerService.saveCustomer(customer);
            }
            this.sale.setCustomer(this.customer);
            if (paymentType.isAtSight()) {
                this.sale.setPaymentType(paymentType);
                this.sale.setTotalValue(totalSighting);
                this.sale.setDiscountType(discountType);
                this.sale.setDiscount(discount);
            } else if (paymentType.isInstallment()) {
                this.sale.setEntryValue(beginValue);
                this.sale.setQuantityOfParcel(this.valueInterestParcel.getInterestParcel().getQtd());
                this.sale.setParcelValue(this.valueInterestParcel.getValue());
            } else if (paymentType.isCustom()) {
                this.sale.setEntryValue(beginValueCustom);
                this.sale.setQuantityOfParcel(qtde.intValue());
                this.sale.setInterest(juros);
                this.sale.setParcelValue(parcelValue);
                this.sale.setTotalValue(totalValueCustom);
            }
            Pending p = new Pending();
            saleService.save(sale);
            lotService.update(lot);
            p.setDataPendencia(new Date());
            p.setDescription("Venda Criada, esperando aprovação.");
            p.setSale(sale);
            p.setStatusSale(StatusSale.WAITING_APPROVAL);
            p.setUsers(userService.getCurrentUserFull());
            pendingService.save(p);
            ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
            FacesContext fc = FacesContext.getCurrentInstance();
            FacesContext.getCurrentInstance().addMessage("msg", new FacesMessage(FacesMessage.SEVERITY_INFO, "Venda Realizada com sucesso.", ""));
            fc.getExternalContext().getFlash().setKeepMessages(true);
            context.redirect("searchsale.xhtml");
        } catch (Exception e) {
            e.printStackTrace();
            Msg.messagemError("Erro ao realizar a venda");
        }

    }

    @PostConstruct
    public void init() throws IOException {
       
        this.enterprise = new Enterprise();
        this.lot = new Lot();
        valueInterestParcel = new ValueInterestParcel();

        this.customer = new Customer();
        this.address = new Address();
        this.addresses = new ArrayList<Address>();
        this.city = new City();
        this.conjuge = new Customer();

        this.annex = new Annex();
        this.annexs = new ArrayList<Annex>();
        this.sale = new Sale();
        this.annexInfo = new Annex();
        this.attachments = new ArrayList<Annex>();

        try {
            this.corrector = correctorService.findCorrectorByUser(userService.getCurrentUser());
        } catch (Exception e) {
            System.err.println("NÃO É ADMIN");
            e.printStackTrace();
            FacesContext context = FacesContext.getCurrentInstance();
            try {
                context.getExternalContext().redirect("permissiondenied.xhtml");
            } catch (IOException ex) {
                Logger.getLogger(ManagerCreateSale.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
        String lotId = params.get("lotId");
        String pathId = params.get("pathId");
        if(lotId != null){
            lot =  lotService.find(Long.parseLong(lotId));
        }
        if(pathId != null){
            lot =  lotService.getLotByPath(pathId);
        }
        
        if(lotId != null || pathId != null){
        if(lot == null || (! lotService.canSale(lot, userService.getCurrentUserFull()))){
            ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
            FacesContext fc = FacesContext.getCurrentInstance();
            FacesContext.getCurrentInstance().addMessage("msg", new FacesMessage(FacesMessage.SEVERITY_INFO, "Este Lote não pode ser vendido", ""));
            fc.getExternalContext().getFlash().setKeepMessages(true);
            context.redirect("indexsale.xhtml");
        }else{
            enterprise = lot.getEnterprise();
            block = Integer.parseInt(lot.getBlock());
            this.loadLot();
        }
        }
    }

    public void verifyCustomer() {
        if (this.customer.getId() == null) {
            this.aux = customerService.existCustomer(customer);
            if (aux != null) {
                RequestContext context = RequestContext.getCurrentInstance();
                context.update("saleForm:customerDlg");
                context.execute("customerDlg.show()");
            }
        }
    }

    public String dimensaoDoLote(){
        if(lot == null || lot.getId() == null){
            return "";
        }
        if(lot.getDimessionX() != null && lot.getDimessionY()!= null){
            return lot.getDimessionX() + " X " + lot.getDimessionY();
        }else{
            return "VARIÁVEL";
        }
    }
    
    public String onFlowProcess(FlowEvent event) {
        return event.getNewStep();
    }

    public String nextStep(FlowEvent event) {
        return event.getNewStep();
    }

    public void loadCustomer() {
        this.customer = aux;
        this.addresses = this.customer.getAddresses() != null ? this.customer.getAddresses() : new ArrayList<Address>();
        this.annexs = this.customer.getAddresses() != null ? this.customer.getAnnexs() : new ArrayList<Annex>();

        if (this.customer.getSpouse() != null) {
            this.conjuge = this.customer.getSpouse();
            conjugeVisible = true;
        } else {
            this.conjuge = new Customer();
            conjugeVisible = false;
        }
        RequestContext context = RequestContext.getCurrentInstance();
        context.execute("customerDlg.hide()");
    }

    public void calcCustomValues() {
        BigDecimal n = this.lot.getSees().subtract(this.beginValueCustom);
        if (hasInterest) {
            n = n.add(n.multiply(juros == null ? new BigDecimal(1) : juros));
        }

        parcelValue = n.divide(qtde.equals(new BigDecimal(0)) ? new BigDecimal(1) : qtde, 2, RoundingMode.UP);
        totalValueCustom = n.add(this.beginValueCustom).setScale(2);
    }

    public void totalValueSees() {
        BigDecimal total = lot.getSees();
        discount = discount == null ? new BigDecimal(0) : discount;
        if (discountType.equals(DiscountType.MONEY)) {
            total = total.subtract(discount);
        } else {
            BigDecimal v = total.divide(new BigDecimal(100), 2, RoundingMode.UP).multiply(discount);
            total = total.subtract(v);
        }
        total.setScale(2);
        this.totalSighting = total;
    }

    public Collection<SelectItem> listParcelas() {
        Collection<SelectItem> lst = new ArrayList<SelectItem>();
        try {
            if (this.lot != null) {
                for (int i = 0; i < this.lot.getValueInterestParcels().size(); i++) {
                    lst.add(new SelectItem(this.lot.getValueInterestParcels().get(i).getId(), this.lot.getValueInterestParcels().get(i).getValue().toString()));
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return lst;
    }

    public List<ValueInterestParcel> parcelas() {
        List<ValueInterestParcel> parcelas = new ArrayList<ValueInterestParcel>();
        try {
            if (this.lot != null && parcelas != null && parcelas.size() > 0) {
                parcelas = this.lot.getValueInterestParcels();
                parcelas = orderParcel(parcelas);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return parcelas;
    }

    public List<ValueInterestParcel> orderParcel(List<ValueInterestParcel> parcelas) {
        Collections.sort(parcelas, new Comparator<ValueInterestParcel>() {

            public int compare(ValueInterestParcel v1, ValueInterestParcel v2) {
                return Integer.compare(v1.getInterestParcel().getQtd(), v2.getInterestParcel().getQtd());
            }
        });
        return parcelas;
    }

    public List<Enterprise> autocompleteEnterprise(String query) {
        return enterpriseService.autocomplete(query);
    }

    public List<SelectItem> lotsByEnterpriseAndBlock() {
        List<SelectItem> items = new ArrayList<SelectItem>();
        List<Lot> lots = lotService.lotsByEnterprise(enterprise, block);
        for (Lot lot : lots) {
            items.add(new SelectItem(lot.getId(), "Lote " + lot.getNum().toString()));
        }
        return items;
    }

    public void loadLot() {
        this.lot = lotService.find(lot.getId());
        this.totalSighting = this.lot.getSees();
        this.beginValue = this.lot.getValueBegin();
        
        canSale =  lotService.canSale(lot, userService.getCurrentUserFull());
    }

    public String parcelLabels(ValueInterestParcel parcel) {
        NumberFormat format = NumberFormat.getInstance(new Locale("pt", "BR"));
        DecimalFormat decimalFormat = new DecimalFormat("###,##0.00", new DecimalFormatSymbols(new Locale("pt", "BR")));
        return parcel.getInterestParcel().getQtd() + " x " + decimalFormat.format(parcel.getValue());
    }

    public List<SelectItem> selectTypeBlock() {
        List<SelectItem> items = new ArrayList<SelectItem>();

        if (enterprise != null && enterprise.getQtdBlock() != null) {
            for (int i = 1; i <= enterprise.getQtdBlock(); i++) {
                items.add(new SelectItem(i, "Quadra " + i));
            }
        }
        return items;
    }

    public List<SelectItem> getDiscountTypes() {
        List<SelectItem> discountTypes = new ArrayList<SelectItem>();
        for (DiscountType ms : DiscountType.values()) {
            discountTypes.add(new SelectItem(ms, ms.getName()));
        }
        return discountTypes;
    }

    public List<SelectItem> getPaymentTypes() {
        List<SelectItem> paymentTypes = new ArrayList<SelectItem>();
        for (PaymentType ms : PaymentType.values()) {
            paymentTypes.add(new SelectItem(ms, ms.getName()));
        }
        return paymentTypes;
    }

    public DiscountType getDiscountType() {
        return discountType;
    }

    public void setDiscountType(DiscountType discountType) {
        this.discountType = discountType;
    }

    public PaymentType getPaymentType() {
        return paymentType;
    }

    public void setPaymentType(PaymentType paymentType) {
        this.paymentType = paymentType;
    }

    public boolean isHasInterest() {
        return hasInterest;
    }

    public void setHasInterest(boolean hasInterest) {
        this.hasInterest = hasInterest;
    }

    public Enterprise getEnterprise() {
        return enterprise;
    }

    public void setEnterprise(Enterprise enterprise) {
        this.enterprise = enterprise;
    }

    public Integer getBlock() {
        return block;
    }

    public void setBlock(Integer block) {
        this.block = block;
    }

    public Lot getLot() {
        return lot;
    }

    public void setLot(Lot lot) {
        this.lot = lot;
    }

    public BigDecimal getDiscount() {
        return discount;
    }

    public void setDiscount(BigDecimal discount) {
        this.discount = discount;
    }

    public BigDecimal getTotalSighting() {
        return totalSighting;
    }

    public void setTotalSighting(BigDecimal totalSighting) {
        this.totalSighting = totalSighting;
    }

    public BigDecimal getBeginValue() {
        return beginValue;
    }

    public void setBeginValue(BigDecimal beginValue) {
        this.beginValue = beginValue;
    }

    public ValueInterestParcel getValueInterestParcel() {
        return valueInterestParcel;
    }

    public void setValueInterestParcel(ValueInterestParcel valueInterestParcel) {
        this.valueInterestParcel = valueInterestParcel;
        System.out.print("oj1 " + this.valueInterestParcel);
    }

    public BigDecimal getBeginValueCustom() {
        return beginValueCustom;
    }

    public void setBeginValueCustom(BigDecimal beginValueCustom) {
        this.beginValueCustom = beginValueCustom;
    }

    public BigDecimal getJuros() {
        return juros;
    }

    public void setJuros(BigDecimal juros) {
        this.juros = juros;
    }

    public BigDecimal getParcelValue() {
        return parcelValue;
    }

    public void setParcelValue(BigDecimal parcelValue) {
        this.parcelValue = parcelValue;
    }

    public BigDecimal getQtde() {
        return qtde;
    }

    public void setQtde(BigDecimal qtde) {
        this.qtde = qtde;
    }

    public BigDecimal getTotalValueCustom() {
        return totalValueCustom;
    }

    public void setTotalValueCustom(BigDecimal totalValueCustom) {
        this.totalValueCustom = totalValueCustom;
    }

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public List<Address> getAddresses() {
        return addresses;
    }

    public void setAddresses(List<Address> addresses) {
        this.addresses = addresses;
    }

    public City getCity() {
        return city;
    }

    public void setCity(City city) {
        this.city = city;
    }

    public void addAddress() {

        address.setCity(city);
        address.setCep(Caracter.removecaracter(address.getCep()));
        addresses.add(address);
        address = new Address();
    }

    public void cleanAddress() {
        this.address = new Address();
    }

    public void edit(Address ad, int id) {
        address = ad;
        if (address.getCity() != null) {
            city = cityService.find(address.getCity().getId());
        }
        addresses.remove(id);
    }

    public void remove(int id) {
        addresses.remove(id);
    }

    public Customer getConjuge() {
        return conjuge;
    }

    public void setConjuge(Customer conjuge) {
        this.conjuge = conjuge;
    }

    public void customerExist() {
        conjuge.setCpf(Caracter.removecaracter(conjuge.getCpf()));
        Customer c = customerService.existCustomer(conjuge);
        if (c != null) {
            conjuge = customerService.find(c.getId());

        }
        if (c == null) {
        }

    }

    public void handle(FileUploadEvent event) throws IOException {
        this.annex = handleAux(event.getFile().getContents(), event.getFile().getFileName(),
                event.getFile().getContentType(), event.getFile().getInputstream());
        this.annexs.add(annex);
        this.annex = new Annex();
    }

    private Annex handleAux(byte[] imageBytes, String nome, String tipo, InputStream is) throws IOException {
        byte[] bytes = null;
        Annex annex = new Annex();
        bytes = imageBytes;
        annex.setType(tipo);
        annex.setDescricao(nome);
        if (bytes != null) {
            annex.setFileByte(bytes);
            Msg.messagemWarn("Anexado com Sucesso ");
        }
        return annex;
    }

    public void handleAnnexInfo(FileUploadEvent event) throws IOException {
        this.annexInfo = handleAux(event.getFile().getContents(), event.getFile().getFileName(),
                event.getFile().getContentType(), event.getFile().getInputstream());

        this.attachments.add(this.annexInfo);
        this.annexInfo = new Annex();
    }

    public Annex getAnnex() {
        return annex;
    }

    public void setAnnex(Annex annex) {
        this.annex = annex;
    }

    public List<Annex> getAnnexs() {
        return annexs;
    }

    public void setAnnexs(List<Annex> annexs) {
        this.annexs = annexs;
    }

    public Customer getAux() {
        return aux;
    }

    public void setAux(Customer aux) {
        this.aux = aux;
    }

    public Sale getSale() {
        return sale;
    }

    public void setSale(Sale sale) {
        this.sale = sale;
    }

    public Annex getAnnexInfo() {
        return annexInfo;
    }

    public void setAnnexInfo(Annex annexInfo) {
        this.annexInfo = annexInfo;
    }

    public Corrector getCorrector() {
        return corrector;
    }

    public void setCorrector(Corrector corrector) {
        this.corrector = corrector;
    }

    public void clearCpf() {
        this.customer.setCpf("");
    }

    public void ajaxTypeCivisStatus() {
        customer.setCivilStatus(customer.getCivilStatus());
        conjugeVisible = customer.getCivilStatus().equals(CivilStatus.CASADO);
    }

    public boolean isConjugeVisible() {
        return conjugeVisible;
    }

    public void setConjugeVisible(boolean conjugeVisible) {
        this.conjugeVisible = conjugeVisible;
    }

    public boolean isAddressRequired() {
        return addressRequired;
    }

    public void setAddressRequired(boolean addressRequired) {
        this.addressRequired = addressRequired;
    }
    
    public void nextInCustomer(){
        this.addressRequired = false;
    }
    
    public void previewInCustomer(){
        this.addressRequired = true;
    }

    public boolean isCanSale() {
        return canSale;
    }

    public void setCanSale(boolean canSale) {
        this.canSale = canSale;
    }
    
    
    
}
